package br.com.naybee.framework.client.freemarker;

import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static br.com.naybee.framework.client.utils.ValidatorUtils.*;
import br.com.naybee.framework.client.models.Model;
import br.com.naybee.framework.client.models.Models;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;

public class FreemarkerTemplate {

	private static final Logger LOGGER = LoggerFactory.getLogger(FreemarkerTemplate.class);

	private FreemarkerTemplate() {
	}

	private final static Map<Class<?>, Configuration> configs = new HashMap<Class<?>, Configuration>();

	public static String parseFile(Class<?> baseClass, String file, Model parameters) {
		try {
			Configuration cfg = configs.get(baseClass);

			if (cfg == null) {
				cfg = new Configuration();
				cfg.setClassForTemplateLoading(baseClass, "sql");
				cfg.setLocalizedLookup(false);
				cfg.setObjectWrapper(new DefaultObjectWrapper());
				configs.put(baseClass, cfg);
			}

			Template t = cfg.getTemplate(file, "UTF-8");

			Model rootModel = Models.newModel();
			rootModel.put(FreeMarkerFunctions.Eq.NAME, new FreeMarkerFunctions.Eq());
			rootModel.put(FreeMarkerFunctions.Empty.NAME, new FreeMarkerFunctions.Empty());
			rootModel.put(FreeMarkerFunctions.Exists.NAME, new FreeMarkerFunctions.Exists());

			if (notEmpty(parameters)) {
				rootModel.putAll(parameters);
			}

			StringWriter writer = new StringWriter();
			t.process(rootModel, writer);
			writer.flush();
			writer.close();

			String parseFile = writer.toString();
			for (Entry<String, Object> entry : parameters.entrySet()) {
				parseFile = parseFile.replace(":" + entry.getKey(), format(entry).toString());
			}
			return parseFile;
		} catch (Exception e) {
			LOGGER.error("Erro ao analisar arquivo \"" + file + "\"");
			throw new RuntimeException(e);
		}
	}

	private static Object format(Entry<String, Object> entry) {
		if (entry.getValue() instanceof String) {
			return "\'" + entry.getValue().toString() + "\'";
		} else if (entry.getValue() instanceof Integer) {
			return Integer.parseInt(entry.getValue().toString());
		}
		return null;
	}
}
